<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\Plugin\WorkMoment\Queue;

use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\AsyncQueue\Annotation\AsyncQueueMessage;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Codec\Json;
use League\Flysystem\FilesystemException;
use MoChat\App\Corp\Logic\AppTrait;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Plugin\ContactTrack\Constants\Event;
use MoChat\Plugin\ContactTrack\Contract\ContactTrackContract;
use MoChat\Plugin\RoomTrack\Constants\EventName;
use MoChat\Plugin\WorkMoment\Contract\WorkMomentCommentContract;
use MoChat\Plugin\WorkMoment\Contract\WorkMomentContract;
use MoChat\Plugin\WorkMoment\Contract\WorkMomentEmployeeContract;

/**
 * 企业微信 朋友圈
 * Class MomentCommentApply.
 */
class MomentCommentQueue
{
    use AppTrait;

    /**
     * @Inject
     * @var WorkMomentContract
     */
    protected $workMomentContract;

    /**
     * @Inject
     * @var WorkMomentEmployeeContract
     */
    protected $workMomentEmployeeContract;

    /**
     * @Inject
     * @var WorkEmployeeContract
     */
    protected $workEmployeeContract;

    /**
     * @Inject
     * @var WorkMomentCommentContract
     */
    protected $workMomentCommentContract;

    /**
     * @Inject
     * @var WorkContactContract
     */
    protected $workContactContract;

    /**
     * @Inject
     * @var StdoutLoggerInterface
     */
    private $logger;

    /**
     * 互动轨迹表.
     * @Inject
     * @var ContactTrackContract
     */
    private $track;

    /**
     * @AsyncQueueMessage(pool="default")
     * @param $corpId
     * @throws InvalidConfigException
     * @throws GuzzleException
     * @throws FilesystemException
     */
    public function handle($corpId): void
    {
        # # 企业创建的朋友圈
        $this->corpMoment($corpId);
        # # 个人创建的朋友圈
        $this->personalMoment($corpId);
    }

    /**
     * 企业创建的朋友圈.
     * @param $corpId
     */
    protected function corpMoment($corpId): void
    {
        $list = $this->workMomentContract->getWorkMomentByCorpIdCreateType($corpId, 0, ['id', 'wx_moment_id']);
        $wx = $this->wxApp($corpId, 'contact')->external_contact_moment;
        foreach ($list as $item) {
            $momentEmployee = $this->workMomentEmployeeContract->getWorkMomentEmployeeByMomentIdPublishStatus($item['id'], 1, ['userid', 'employee_id']);
            foreach ($momentEmployee as $val) {
                $result = $wx->getComments($item['wxMomentId'], $val['userid']);
                if ($result['errcode'] !== 0) {
                    $this->logger->error('获取客户朋友圈的互动数据失败' . Json::encode($result));
                    return;
                }
                $employee = $this->workEmployeeContract->getWorkEmployeeById($val['employeeId'], ['name']);
                $employeeName = $employee['name'] ?? '';
                # # 数据操作
                Db::beginTransaction();
                try {
                    # # 点赞记录
                    if (! empty($result['like_list'])) {
                        $this->likeComment($corpId, $result['like_list'], $item['wxMomentId'], $item['id'], 1, $employeeName);
                    }

                    # # 评论记录
                    if (! empty($result['comment_list'])) {
                        $this->likeComment($corpId, $result['comment_list'], $item['wxMomentId'], $item['id'], 2, $employeeName);
                    }
                    Db::commit();
                } catch (\Throwable $e) {
                    Db::rollBack();
                    $this->logger->error(sprintf('%s [%s] %s', '朋友圈记录创建失败', date('Y-m-d H:i:s'), $e->getMessage()));
                    $this->logger->error($e->getTraceAsString());
                    throw new CommonException(ErrorCode::SERVER_ERROR, $e->getMessage()); // '活动创建失败'
                }
            }
        }
    }

    /**
     * 个人创建的朋友圈.
     * @param $corpId
     */
    protected function personalMoment($corpId): void
    {
        $list = $this->workMomentContract->getWorkMomentByCorpIdCreateType($corpId, 1, ['id', 'wx_moment_id', 'creator', 'employee_id']);
        $wx = $this->wxApp($corpId, 'contact')->external_contact_moment;
        foreach ($list as $item) {
            $result = $wx->getComments($item['wxMomentId'], $item['creator']);
            if ($result['errcode'] !== 0) {
                $this->logger->error('客户朋友圈的互动数据失败' . Json::encode($result));
                return;
            }
            $employee = $this->workEmployeeContract->getWorkEmployeeById($item['employeeId'], ['name']);
            $employeeName = $employee['name'] ?? '';
            # # 数据操作
            Db::beginTransaction();
            try {
                # # 点赞记录
                if (! empty($result['like_list'])) {
                    $this->likeComment($corpId, $result['like_list'], $item['wxMomentId'], $item['id'], 1, $employeeName);
                }

                # # 评论记录
                if (! empty($result['comment_list'])) {
                    $this->likeComment($corpId, $result['comment_list'], $item['wxMomentId'], $item['id'], 2, $employeeName);
                }

                Db::commit();
            } catch (\Throwable $e) {
                Db::rollBack();
                $this->logger->error(sprintf('%s [%s] %s', '客户朋友圈的互动数据创建失败', date('Y-m-d H:i:s'), $e->getMessage()));
                $this->logger->error($e->getTraceAsString());
                throw new CommonException(ErrorCode::SERVER_ERROR, $e->getMessage()); // '活动创建失败'
            }
        }
    }

    /**
     * 保存互动数据.
     */
    protected function likeComment(int $corpId, array $list, string $wxMomentId, int $momentId, int $type, string $employeeName): void
    {
        $data = [];
        foreach ($list as $k => $v) {
            # # 客户
            if (! empty($v['external_userid']) && ! empty($this->workMomentCommentContract->getWorkMomentCommentByWxMomentIdExternalUseridType($wxMomentId, $v['external_userid'], $type))) {
                continue;
            }
            # # 客户
            if (! empty($v['userid']) && ! empty($this->workMomentCommentContract->getWorkMomentCommentByWxMomentIdUserIdType($wxMomentId, $v['userid'], $type))) {
                continue;
            }

            $employee = empty($v['userid']) ? [] : $this->workEmployeeContract->getWorkEmployeeByCorpIdWxUserId((string) $corpId, $v['userid'], ['id', 'log_user_id']);
            $contact = empty($v['external_userid']) ? [] : $this->workContactContract->getWorkContactByCorpIdWxExternalUserId($corpId, $v['external_userid'], ['id', 'name']);
            $contactId = $contact['id'] ?? 0;
            $employeeId = empty($employee) ? 0 : $employee[0]['id'];
            $data[$k] = [
                'moment_id' => $momentId,
                'wx_moment_id' => $wxMomentId,
                'type' => $type,
                'contact_id' => $contactId,
                'external_userid' => $v['external_userid'] ?? '',
                'employee_id' => $employeeId,
                'userid' => $v['userid'] ?? '',
                'create_time' => $v['create_time'],
                'created_at' => date('Y-m-d H:i:s'),
            ];
            # # 记录轨迹
            if ($type === 1) {
                if ($contactId > 0) {
                    $this->recordTrack($employeeId, $contactId, $type, $contact['name'] . '给' . $employeeName . '的朋友圈点赞', $corpId);
                }
            } else {
                if ($contactId > 0) {
                    $this->recordTrack($employeeId, $contactId, $type, $contact['name'] . '给' . $employeeName . '的朋友圈评论', $corpId);
                }
            }
        }
        if (! empty($data)) {
            $this->workMomentCommentContract->createWorkMomentComments(array_merge($data));
        }
    }

    /**
     * 记录轨迹.
     * @param $employeeId
     * @param $contactId
     * @param $type
     * @param $content
     * @param $corpId
     */
    private function recordTrack($employeeId, $contactId, $type, $content, $corpId)
    {
        $jsonContact = [
            'title' => $type === 1 ? EventName::MOMENT_LIKE : EventName::MOMENT_COMMENT,
            'content' => $content,
        ];
        $data = [
            'employee_id' => $employeeId,
            'contact_id' => $contactId,
            'content' => Json::encode($jsonContact),
            'corp_id' => $corpId,
            'event' => Event::MOMENT,
        ];

        $res = $this->track->createContactTrack($data);
        if (! is_int($res)) {
            throw new CommonException(ErrorCode::SERVER_ERROR, '记录轨迹失败');
        }
    }
}
